package implementation;

import com.thoughtworks.xstream.XStream;
import entities.Medium;
import entities.Movie;
import java.util.ArrayList;
import java.util.List;
import managers.CentralManager;
import managers.MediumManager;
import managers.MovieManager;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.exist.xmldb.EXistResource;
import org.xmldb.api.base.*;
import org.xmldb.api.modules.XQueryService;
import utilities.DBUtils;
import utilities.MediumConverter;

/**
 *
 * @author Hacnar
 */
public class CentralManagerImpl implements CentralManager{

    @Override
    public List<Movie> getMoviesOnMedium(Medium medium) {
        if (medium == null) {
            throw new IllegalArgumentException("Error: medium is null");
        }
        if (medium.getId() == null) {
            throw new IllegalArgumentException("Error: medium id is null");
        }
        List<Movie> movies = new ArrayList<Movie>();
        List<String> movieIds = medium.getMovies();
        MovieManager movieMngr = new MovieManagerImpl();
        for (Movie m : movieMngr.getAllMovies()) {
            if (movieIds.contains(m.getId())) movies.add(m);
        }
        return movies;
    }

    @Override
    public List<Medium> getMediaWithMovie(Movie movie) {
        if (movie == null) {
            throw new IllegalArgumentException("Error: movie is null");
        }
        if (movie.getId() == null) {
            throw new IllegalArgumentException("Error: movie id is null");
        }
        
        String query = "for $medium in collection('/db/media')/medium "+
            "let $id:=$medium/movies/movie/id "+
            "where $id='"+movie.getId()+"' "+
            "return $medium";
        List<Medium> media = new ArrayList<Medium>();
        
        DBUtils.openDBConnection();
        Collection col = null;
        try { 
            col = DBUtils.getOrCreateCollection("/media");
            XQueryService xqs = (XQueryService)col.getService("XQueryService", "1.0");
            xqs.setProperty("indent", "yes");
            
            CompiledExpression compiled = xqs.compile(query);
            ResourceSet result = xqs.execute(compiled);
            ResourceIterator i = result.getIterator();
            Resource res = null;
            while(i.hasMoreResources()) {
                try {
                    res = i.nextResource();
                    XStream xStream = new XStream();
                    xStream.registerConverter(new MediumConverter());
                    xStream.alias("medium", Medium.class);
                    Medium medium = (Medium)xStream.fromXML("<?xml version=\"1.0\"?>"+res.getContent().toString());
                    medium.setId(res.getId());
                    media.add(medium);
                } catch (XMLDBException ex) {
                    Logger.getLogger(MovieManagerImpl.class.getName()).log(Level.ERROR, null, ex);
                } finally {
                    try { ((EXistResource)res).freeResources(); } catch(XMLDBException ex) {
                        Logger.getLogger(MovieManagerImpl.class.getName()).log(Level.ERROR, null, ex);
                    }
                }
            }
        } catch (XMLDBException ex) {
            Logger.getLogger(MovieManagerImpl.class.getName()).log(Level.ERROR, null, ex);
        } finally {
            if(col != null) {
                try { col.close(); } catch(XMLDBException ex) {
                    Logger.getLogger(MovieManagerImpl.class.getName()).log(Level.ERROR, null, ex);
                }
            }
            DBUtils.closeDB();
        }
        return media;
    }

    @Override
    public void putMovieOnMedium(Movie movie, Medium medium) {
        if (medium == null) {
            throw new IllegalArgumentException("Error: medium is null");
        }
        if (medium.getId() == null) {
            throw new IllegalArgumentException("Error: medium id is null");
        }
        if (movie == null) {
            throw new IllegalArgumentException("Error: movie is null");
        }
        if (movie.getId() == null) {
            throw new IllegalArgumentException("Error: movie id is null");
        }
        MediumManager mediumMngr = new MediumManagerImpl();
        List<String> movies = medium.getMovies();
        movies.add(movie.getId());
        medium.setMovies(movies);
        movie.setMedium(medium);
        mediumMngr.updateMedium(medium);        
    }

    @Override
    public void removeMovieFromMedium(Movie movie, Medium medium) {
        if (medium == null) {
            throw new IllegalArgumentException("Error: medium is null");
        }
        if (medium.getId() == null) {
            throw new IllegalArgumentException("Error: medium id is null");
        }
        if (movie == null) {
            throw new IllegalArgumentException("Error: movie is null");
        }
        if (movie.getId() == null) {
            throw new IllegalArgumentException("Error: movie id is null");
        }
        
        MediumManager mediumMngr = new MediumManagerImpl();
        List<String> movies = medium.getMovies();
        movies.remove(movie.getId());
        medium.setMovies(movies);
        mediumMngr.updateMedium(medium);
    }
    
}
